/**********************************************************************
 *   Copyright: (C)2024 LingYun IoT System Studio
 *      Author: LiJiahui<2199250859@qq.com>
 *
 * Description: The purpose of this code is to provide a simple C library,
 *              which providing software bit-bang of the I2C protocol on
 *              any GPIO pins for ISKBoard.
 *
 *   ChangeLog:
 *        Version    Date       Author            Description
 *        V1.0.0  2024.08.29    LiJiahui      Release initial version
 *
 ***********************************************************************/

#ifndef INC_MAX30102_H_
#define INC_MAX30102_H_

#include "project_tasks.h"

// 定义传感器数据结构体
typedef struct {
    uint8_t heart_rate;
    uint8_t spo2;
} SensorData_t;

#define MAX30102_I2CBUS		I2CBUS1

#define MAX30102_ADDR       0x57 // 7-bit 地址

#define REG_MODE_CONFIG		0x09 //MAX30102模式配置寄存器
#define REG_INTR_STATUS_1	0x00 //中断状态寄存器1，可以清除 A_FULL、PPG_RDY 和 ALC_OVF 中断
#define REG_INTR_STATUS_2	0x01 //中断状态寄存器2
#define REG_INTR_ENABLE_1	0x02 //中断使能寄存器1，可以使能A_FULL_EN,PRG_RDY_EN,ALC_OVF_EN
#define REG_INTR_ENABLE_2	0x03 //中断使能寄存器2，内部温度传感器数据准备好中断使能
#define REG_FIFO_WR_PTR		0x04 //FIFO写指针，即下一个数据被写入的FIFO位置
#define REG_OVF_COUNTER		0x05 //FIFO溢出器，用于计数FIFO溢出次数
#define REG_FIFO_RD_PTR		0x06 //FIFO读指针，即下一个数据被读取的位置
#define REG_FIFO_DATA		0x07 //FIFO数据寄存器，从这里读取红光和红外光的数据
#define REG_FIFO_CONFIG		0x08 //FIFO配置寄存器
#define REG_SPO2_CONFIG		0x0A //SPO2模式配置寄存器 该寄存器的ADC Range (ADC_RGE) 位和 LED Pulse Width (LED_PW) 位共同影响“积分时间”和“分辨率”。
#define REG_LED1_PA			0x0C //LED1(红光)的脉冲幅度设置 和红外光一样用来设置LED的驱动电流
#define REG_LED2_PA			0x0D //LED2(红外光)的脉冲幅度设置
#define REG_SLOT1			0x11
#define REG_SLOT2			0x12


// 温度
#define MAX30102_REG_TEMP_INTG         0x1F
#define MAX30102_REG_TEMP_FRAC         0x20

// 复位、关机控制
#define MAX30102_REG_REV_ID            0xFE
#define MAX30102_REG_PART_ID           0xFF

#define WINDOW_SHIFT             100        // 每次更新采样数量（窗口滑动步长）
#define SMOOTHING_FACTOR         0.1f       // 平滑因子
#define TOUCH_THRESHOLD          12000      // IR判定手指贴合阈值，可根据实测微调
#define sample_interval          1000
#define STABILITY_THRESHOLD      5          // 连续几个采样点稳定才认为手指存在
#define STABLE_TIME_WINDOW       500        // 在这段时间内手指信号不稳定时保持不更新输出

#define true                           1
#define false                          0
#define FS                             100
#define BUFFER_SIZE                    (FS* 5)
#define HR_FIFO_SIZE                   7
#define MA4_SIZE                       4 // DO NOT CHANGE
#define HAMMING_SIZE                   5// DO NOT CHANGE
#define min(x,y)                       ((x) < (y) ? (x) : (y))

extern int max30102_write_reg(uint8_t reg_addr, uint8_t value);
extern int max30102_read_reg(uint8_t reg_addr, uint8_t *buf, int size);
extern void max30102_reset(void);
extern void MAX30102_Init(void);

extern int MAX30102_Read_FIFO(uint32_t* red_led, uint32_t* ir_led);
extern void MAX30102_ClearInterrupt(void);

extern void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer,  int32_t n_ir_buffer_length, uint32_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid,
        int32_t *pn_heart_rate, int8_t  *pch_hr_valid);
extern void maxim_find_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num);
extern void maxim_peaks_above_min_height(int32_t *pn_locs, int32_t *pn_npks, int32_t  *pn_x, int32_t n_size, int32_t n_min_height);
extern void maxim_remove_close_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_min_distance);
extern void maxim_sort_ascend(int32_t *pn_x,int32_t n_size);
extern void maxim_sort_indices_descend(int32_t *pn_x, int32_t *pn_indx, int32_t n_size);
void GetData_Max30102(void);

void max30102_init_buffer(void);
SensorData_t max30102_process_data(void);



#endif /* INC_MAX30102_H_ */
